//
//  FQDAccountManager.m
//  FakeQDaily
//
//  Created by mewxiv on 9/7/16.
//  Copyright © 2016 Xensius. All rights reserved.
//

#import "FQDAccountManager.h"
#import "FQDDataBase.h"
#import "QDailyAPI.h"
#import "FQDRestModel.h"
#import "MBProgressHUD+FQDExtension.h"

#import "YYModel.h"

static NSString *const kUserInfoTableName = @"fqd_userinfo";

@interface FQDAccountManager ()

@property (nonatomic, readwrite, strong) FQDUser *currentUser;
@property (nonatomic, copy) NSString *currentAppSession;

@end

@implementation FQDAccountManager
@synthesize currentUser = _currentUser;

+ (instancetype)sharedManager
{
    static FQDAccountManager *manager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self class] new];
    });
    return manager;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self setupDataTable];
        [self setupNotifications];
        [self loadCookies];
        [self updateCurrentAppSession];
    }
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)setupNotifications
{
    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
    [defaultCenter addObserver:self
                      selector:@selector(applicationDidEnterBackground:)
                          name:UIApplicationDidEnterBackgroundNotification
                        object:nil];
    [defaultCenter addObserver:self
                      selector:@selector(applicationWillTerminate:)
                          name:UIApplicationWillTerminateNotification
                        object:nil];
    [defaultCenter addObserver:self
                      selector:@selector(appSessionCookieDidChanged:)
                          name:FQDAppCookiesDidChangeNotification
                        object:nil];
}

- (void)setupDataTable
{
    NSDictionary *columns = @{
        @"qdID" : @"VARCHAR PRIMARY KEY",
        @"userId" : @"VARCHAR",
        @"alias" : @"VARCHAR",
        @"username" : @"VARCHAR",
        @"avatarURLString" : @"VARCHAR",
        @"signature" : @"VARCHAR",
        @"email" : @"VARCHAR",
        @"phone" : @"VARCHAR",
        @"messageCount" : @"INTEGER",
        @"connectedToWeibo" : @"INTEGER",
        @"connectedToQQ" : @"INTEGER",
        @"connectedToWechat" : @"INTEGER",
        @"connectedToTwitter" : @"INTEGER",
        @"openCommentPush" : @"INTEGER",
        @"openPraisesPush" : @"INTEGER",
        @"openLetterPush" : @"INTEGER",
        @"appSession" : @"VARCHAR",
    };

    FQDDatabase *database = [FQDDatabase sharedDatabase];
    [database createTableIfNotExist:kUserInfoTableName columns:columns];
    
}

- (void)autoLogin
{
    if (self.currentAppSession) {
        
        FQDDatabase *database = [FQDDatabase sharedDatabase];
        NSString *condition = [NSString stringWithFormat:@"appSession = '%@'", self.currentAppSession];
        NSDictionary *userDict = [[database selectAllColumnsFromTable:kUserInfoTableName whereCondition:condition] firstObject];
        
        if (userDict) {
            FQDUser *user = [[FQDUser alloc] init];
            for (NSString *propertyName in userDict) {
                [user setValue:userDict[propertyName] forKey:propertyName];
            }
            self.currentUser = user;
            
            [self fetchUserSubscription:YES];
        }
    }
    [self fetchUserRadar];
}

- (void)loginWithPhone:(NSString *)phone password:(NSString *)password remember:(BOOL)remember completion:(void (^)(BOOL success))completion
{
    [MBProgressHUD showLoadingAnim];
    [[QDailyAPI sharedAPI] loginWithPhone:phone password:password remember:remember
     completion:^(id responseObject, NSError *error) {
        [MBProgressHUD hideLoadingAnim];
        if (responseObject) {
            NSNumber *status = [responseObject valueForKeyPath:@"meta.status"];
            if ([status integerValue] == 200) {
                id response = responseObject[@"response"];
                FQDUser *user = [FQDUser yy_modelWithJSON:response];
                [self changeCurrentUser:user];

                [self fetchUserSubscription:NO];
                completion(YES);
            } else {
                NSString *msg = [responseObject valueForKeyPath:@"meta.msg"];
                [MBProgressHUD showMessage:msg];
                completion(NO);
            }
        } else {
            [MBProgressHUD showMessage:@"登录失败"];
            FQDLog(@"Fail to Login:%@", [error localizedDescription]);
            completion(NO);
        }

    }];
}

- (void)loginWithEmail:(NSString *)email password:(NSString *)password remember:(BOOL)remember completion:(void (^)(BOOL success))completion
{
    [MBProgressHUD showLoadingAnim];
    [[QDailyAPI sharedAPI] loginWithEmail:email password:password remember:remember completion:^(id responseObject, NSError *error) {
        [MBProgressHUD hideLoadingAnim];
        if (responseObject) {
            NSNumber *status = [responseObject valueForKeyPath:@"meta.status"];
            if ([status integerValue] == 200) {
                id response = responseObject[@"response"];
                FQDUser *user = [FQDUser yy_modelWithJSON:response];
                [self changeCurrentUser:user];
                
                [self fetchUserSubscription:NO];
                completion(YES);
            } else {
                NSString *msg = [responseObject valueForKeyPath:@"meta.msg"];
                [MBProgressHUD showMessage:msg];
                completion(NO);
            }
        } else {
            [MBProgressHUD showMessage:@"登录失败"];
            FQDLog(@"Fail to Login:%@", [error localizedDescription]);
            completion(NO);
        }
    }];
}

- (void)logout:(void (^)(BOOL success))completion
{
    [MBProgressHUD showLoadingAnim];
    [[QDailyAPI sharedAPI] logout:^(id responseObject, NSError *error) {
        if (responseObject) {
            NSNumber *status = [responseObject valueForKeyPath:@"meta.status"];
            if ([status integerValue] == 200) {
                [self changeCurrentUser:nil];
                [self fetchUserSubscription:NO];
                completion(YES);
            } else {
                NSString *msg = [responseObject valueForKeyPath:@"meta.msg"];
                FQDLog(@"Fail to Logout:%@", [msg description]);
                completion(NO);
            }
        } else {
            completion(NO);
            FQDLog(@"Fail to Logout:%@", [error localizedDescription]);
        }
        [MBProgressHUD hideLoadingAnim];
    }];
}

- (void)changeCurrentUser:(FQDUser *)user
{
    self.currentUser = user;
    if (user) {
        [self saveUserAccount:user];
    }
}

- (void)saveUserAccount:(FQDUser *)user
{
    NSString *appSession = self.currentAppSession;
    NSDictionary *columnValues = @{
        @"qdID" : user.qdID,
        @"userId" : user.userId,
        @"alias" : user.alias ? : @"",
        @"username" : user.username ? : @"",
        @"avatarURLString" : user.avatarURLString ? : @"",
        @"signature" : user.signature ? : @"",
        @"email" : user.email ? : @"",
        @"phone" : user.phone ? : @"",
        @"messageCount" : @(user.messageCount),
        @"connectedToWeibo" : @(user.connectedToWeibo),
        @"connectedToQQ" : @(user.connectedToQQ),
        @"connectedToWechat" : @(user.connectedToWechat),
        @"connectedToTwitter" : @(user.connectedToTwitter),
        @"openCommentPush" : @(user.openCommentPush),
        @"openPraisesPush" : @(user.openPraisesPush),
        @"openLetterPush" : @(user.openLetterPush),
        @"appSession" : appSession ? : @"",
    };

    FQDDatabase *database = [FQDDatabase sharedDatabase];
    [database insertOrReplaceIntoTable:kUserInfoTableName columnValues:columnValues];
}

- (void)fetchUserSubscription:(BOOL)shouldFetchUserCenterInfo
{
    [self fetchUserRadar];

    if (self.currentUser.userId) {
        [[QDailyAPI sharedAPI] getUserSubscription:self.currentUser.userId
         completion:^(id responseObject, NSError *error) {

        }];
    }

    
    if (shouldFetchUserCenterInfo) {
        [[QDailyAPI sharedAPI] getUserCenter:^(id responseObject, NSError *error) {
            
        }];
    }
}

- (void)fetchUserRadar
{
    [[QDailyAPI sharedAPI] getUserRadar:^(id responseObject, NSError *error) {
        NSNumber *status = [responseObject valueForKeyPath:@"meta.status"];
        if ([status integerValue] == 200) {
            id response = responseObject[@"response"];
            self.radarItems = [NSArray yy_modelArrayWithClass:[FQDRadarItem class]
                                                         json:response[@"radars"]];
            NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
            [defaultCenter postNotificationName:FQDUserRadarDidChangeNotification object:nil];
        }
    }];
}

- (void)updateCurrentAppSession
{
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
    for (NSHTTPCookie *cookie in cookies) {
        if ([cookie.name isEqualToString:@"_qdaily3_app_session"]) {
            self.currentAppSession = cookie.value;
        }
    }
}

- (void)updateLoginedUserAppSessionData
{
    NSString *appSession = self.currentAppSession;
    if (self.currentUser) {
        NSDictionary *updateValues = @{
            @"appSession" : appSession,
        };
        NSString *whereCondition = [NSString stringWithFormat:@"qdID = '%@'", self.currentUser.qdID];
        FQDDatabase *database = [FQDDatabase sharedDatabase];
        [database updateTable:kUserInfoTableName
              setColumnValues:updateValues
               whereCondition:whereCondition];
    }
}

#pragma mark - Cookies automatically save and load
- (void)saveCookies
{
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
    NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject:cookies];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:cookiesData forKey:kQDailyCookiesUserDefaultsKey];
    [defaults synchronize];
}

- (void)loadCookies
{
    NSData *cookiesData = [[NSUserDefaults standardUserDefaults] objectForKey:kQDailyCookiesUserDefaultsKey];
    NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesData];
    
    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    for (NSHTTPCookie *cookie in cookies) {
        [cookieStorage setCookie:cookie];
    }
    
}

#pragma mark - Notifications
- (void)applicationDidEnterBackground:(NSNotification *)note
{
    [self saveCookies];
}

- (void)applicationWillTerminate:(NSNotification *)note
{
    [self saveCookies];
}

- (void)appSessionCookieDidChanged:(NSNotification *)note
{
    [self updateCurrentAppSession];
    [self updateLoginedUserAppSessionData];
}

#pragma mark - Getters and Setters

- (BOOL)isLogined
{
    return (self.currentUser != nil);
}

- (void)setCurrentUser:(FQDUser *)currentUser
{
    if (_currentUser == currentUser) {
        return;
    }
    
    _currentUser = currentUser;
    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
    [defaultCenter postNotificationName:FQDAccountUserInfoDidChangeNotification
                                 object:nil];
}

- (FQDUser *)currentUser
{
    return [_currentUser copy];
}

- (NSString *)currentUserId
{
    if (_currentUser) {
        return _currentUser.userId;
    }
    return @"0";
}

@end
